package cn.tworice.cryption.service.impl;

import cn.tworice.cryption.config.CryptionProperties;
import cn.tworice.cryption.service.CryptService;
import javax.crypto.*;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.util.Arrays;
import java.util.Base64;


/**
 * AES-GCM加解密实现类
 */
public class AesGcmServiceImpl implements CryptService {
    // AES-GCM参数配置
    private static final int GCM_IV_LENGTH = 12;    // IV长度（推荐12字节）
    private static final int GCM_TAG_LENGTH = 128;  // 认证标签长度（128位）
    private static final String ALGORITHM = "AES/GCM/NoPadding";

    private final SecretKey secretKey;
    private final SecureRandom secureRandom = new SecureRandom();



    /**
     * 构造函数（使用随机生成的密钥）
     */
    public AesGcmServiceImpl() {
        try {
            // 生成AES-256密钥
            KeyGenerator keyGen = KeyGenerator.getInstance("AES");
            keyGen.init(256);
            this.secretKey = keyGen.generateKey();
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("密钥生成失败", e);
        }
    }

    /**
     * 构造函数（使用现有密钥）
     * @param key 二进制格式的密钥（长度必须符合AES要求）
     */
    public AesGcmServiceImpl(byte[] key) {
        // 验证密钥长度（支持128/192/256位）
        if (key.length != 16 && key.length != 24 && key.length != 32) {
            throw new IllegalArgumentException("无效的密钥长度");
        }
        this.secretKey = new SecretKeySpec(key, "AES");
    }

    @Override
    public String encrypt(String plaintext) {
        try {
            // 生成随机IV
            byte[] iv = new byte[GCM_IV_LENGTH];
            secureRandom.nextBytes(iv);

            // 初始化加密器
            Cipher cipher = Cipher.getInstance(ALGORITHM);
            cipher.init(
                    Cipher.ENCRYPT_MODE,
                    secretKey,
                    new GCMParameterSpec(GCM_TAG_LENGTH, iv)
            );

            // 执行加密（包含认证标签）
            byte[] ciphertext = cipher.doFinal(plaintext.getBytes(StandardCharsets.UTF_8));

            // 组合IV和密文
            byte[] combined = new byte[iv.length + ciphertext.length];
            System.arraycopy(iv, 0, combined, 0, iv.length);
            System.arraycopy(ciphertext, 0, combined, iv.length, ciphertext.length);

            return Base64.getEncoder().encodeToString(combined);
        } catch (Exception e) {
            throw new RuntimeException("加密失败", e);
        }
    }

    @Override
    public String decrypt(String encryptedText) {
        try {
            // 解码Base64
            byte[] combined = Base64.getDecoder().decode(encryptedText);

            // 验证最小长度
            if (combined.length < GCM_IV_LENGTH) {
                throw new IllegalArgumentException("无效的加密数据");
            }

            // 分离IV和密文
            byte[] iv = Arrays.copyOfRange(combined, 0, GCM_IV_LENGTH);
            byte[] ciphertext = Arrays.copyOfRange(combined, GCM_IV_LENGTH, combined.length);

            // 初始化解密器
            Cipher cipher = Cipher.getInstance(ALGORITHM);
            cipher.init(
                    Cipher.DECRYPT_MODE,
                    secretKey,
                    new GCMParameterSpec(GCM_TAG_LENGTH, iv)
            );

            // 执行解密（自动验证认证标签）
            byte[] plaintext = cipher.doFinal(ciphertext);

            return new String(plaintext, StandardCharsets.UTF_8);
        } catch (IllegalBlockSizeException | BadPaddingException e) {
            throw new RuntimeException("解密失败（可能密钥错误或数据损坏）", e);
        } catch (Exception e) {
            throw new RuntimeException("解密失败", e);
        }
    }

    /**
     * 获取当前密钥（Base64编码）
     */
    public String getBase64Key() {
        return Base64.getEncoder().encodeToString(secretKey.getEncoded());
    }
}
